package cn.heyige.backend.service.ai;

import cn.heyige.backend.dto.ChatDto;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * AI模型管理器 - 精简版
 *
 * 专注于核心AI模型管理功能，提高系统性能和可维护性
 * 增强错误处理和模型选择逻辑
 *
 * @author CodeBuddy
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiModelManager {

    private final List<AiModelService> modelServices;
    
    private static final int DEFAULT_TIMEOUT_SECONDS = 30;
    private static final int MAX_PRIORITY = Integer.MAX_VALUE;

    /**
     * 聊天请求，支持自动降级
     *
     * @param request 聊天请求
     * @return 聊天响应
     */
    public ChatDto.ChatResponse chatWithFallback(ChatDto.ChatRequest request) {
        // 参数校验
        if (request == null) {
            throw new IllegalArgumentException("聊天请求不能为空");
        }

        // 如果指定了模型，优先使用指定模型
        if (StringUtils.hasText(request.getModel())) {
            for (AiModelService service : modelServices) {
                if (service.getModelName().equals(request.getModel()) && service.isAvailable()) {
                    try {
                        return service.chat(request);
                    } catch (Exception e) {
                        log.error("指定模型 {} 调用失败，尝试其他模型", request.getModel(), e);
                        break;
                    }
                }
            }
        }

        // 按优先级尝试可用模型
        List<AiModelService> availableServices = new ArrayList<>();
        for (AiModelService service : modelServices) {
            if (service.isAvailable()) {
                availableServices.add(service);
            }
        }

        // 按优先级排序
        availableServices.sort(Comparator.comparingInt(AiModelService::getPriority));

        // 尝试调用可用模型
        for (AiModelService service : availableServices) {
            try {
                log.info("尝试使用模型: {}", service.getModelName());
                return service.chat(request);
            } catch (Exception e) {
                log.error("模型 {} 调用失败，尝试下一个模型", service.getModelName(), e);
                // 继续尝试下一个模型
            }
        }

        throw new RuntimeException("所有AI模型都不可用或调用失败");
    }

    /**
     * 并行调用多个模型，选择最快响应的结果
     *
     * @param request 聊天请求
     * @return 聊天响应
     */
    public ChatDto.ChatResponse chatWithParallel(ChatDto.ChatRequest request) {
        // 参数校验
        if (request == null) {
            throw new IllegalArgumentException("聊天请求不能为空");
        }

        // 创建并行任务
        List<CompletableFuture<ChatDto.ChatResponse>> futures = new ArrayList<>();

        for (AiModelService service : modelServices) {
            if (service.isAvailable()) {
                CompletableFuture<ChatDto.ChatResponse> future = CompletableFuture.supplyAsync(() -> {
                    try {
                        return service.chat(request);
                    } catch (Exception e) {
                        log.error("模型 {} 调用失败", service.getModelName(), e);
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }
        }

        if (futures.isEmpty()) {
            throw new RuntimeException("没有可用的AI模型");
        }

        try {
            // 等待任意一个任务完成，设置超时时间
            CompletableFuture<Object> anyOf = CompletableFuture.anyOf(
                    futures.toArray(new CompletableFuture[0])
            );

            // 设置默认超时时间
            return (ChatDto.ChatResponse) anyOf.get(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("AI模型调用被中断");
        } catch (ExecutionException e) {
            throw new RuntimeException("所有AI模型调用失败");
        } catch (TimeoutException e) {
            throw new RuntimeException("AI模型调用超时");
        }
    }

    /**
     * 获取所有可用模型列表
     *
     * @return 可用模型列表
     */
    public List<String> getAvailableModels() {
        List<String> availableModels = new ArrayList<>();
        for (AiModelService service : modelServices) {
            if (service.isAvailable()) {
                availableModels.add(service.getModelName());
            }
        }
        return availableModels;
    }

    /**
     * 检查指定模型是否可用
     *
     * @param modelName 模型名称
     * @return 是否可用
     */
    public boolean isModelAvailable(String modelName) {
        // 参数校验
        if (!StringUtils.hasText(modelName)) {
            return false;
        }

        for (AiModelService service : modelServices) {
            if (service.getModelName().equals(modelName)) {
                return service.isAvailable();
            }
        }
        return false;
    }

    /**
     * 获取模型优先级
     *
     * @param modelName 模型名称
     * @return 优先级
     */
    public int getModelPriority(String modelName) {
        // 参数校验
        if (!StringUtils.hasText(modelName)) {
            return MAX_PRIORITY;
        }

        for (AiModelService service : modelServices) {
            if (service.getModelName().equals(modelName)) {
                return service.getPriority();
            }
        }
        return MAX_PRIORITY;
    }

    /**
     * 获取所有模型状态
     *
     * @return 模型状态列表
     */
    public List<ModelStatus> getModelStatuses() {
        List<ModelStatus> statuses = new ArrayList<>();
        for (AiModelService service : modelServices) {
            ModelStatus status = new ModelStatus();
            status.setModelName(service.getModelName());
            status.setAvailable(service.isAvailable());
            status.setPriority(service.getPriority());
            statuses.add(status);
        }
        return statuses;
    }

    /**
     * 模型状态信息
     */
    @Setter
    @Getter
    public static class ModelStatus {
        private String modelName;
        private boolean available;
        private int priority;
    }
}